package edu.berkeley.cs160.innovationers.shoppersidekick.sync;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import com.google.android.c2dm.C2DMessaging;

import edu.berkeley.cs160.innovationers.shoppersidekick.Config;
import edu.berkeley.cs160.innovationers.shoppersidekick.Item;
import edu.berkeley.cs160.innovationers.shoppersidekick.ShoppingList;
import edu.berkeley.cs160.innovationers.shoppersidekick.myApp;
import android.content.Context;
import android.util.Log;

public class RPCClient {
	
	public static JSONObject execute(JSONRPCMethod jsonRPCMethod) {
        Log.d(Config.SS_TAG, "executing rpc method: " + jsonRPCMethod.getMethodName());

		DefaultHttpClient mHttpClient = new DefaultHttpClient();
		HttpResponse httpResponse;
		
		HttpPost httpPost = new HttpPost(Config.RPC_SERVLET_URL);
        JSONObject requestJson = new JSONObject();
        
        
        try {
        	JSONArray jsonCalls = new JSONArray();
        	jsonCalls.put(0, jsonRPCMethod.toJSONObject());
        	requestJson.put("calls", jsonCalls);
        	httpPost.setEntity(new StringEntity(requestJson.toString(), "UTF-8"));
        	
        	//execute and get server response
			httpResponse = mHttpClient.execute(httpPost);
			
			final int responseStatusCode = httpResponse.getStatusLine().getStatusCode();
            if (200 <= responseStatusCode && responseStatusCode < 300) {
            	BufferedReader reader = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent(), "UTF-8"), 8 * 1024); //TODO what is the 8*1024 for ?? why not default size
            	
            	StringBuilder sb = new StringBuilder();
                String line;
                
                while ((line = reader.readLine()) != null) {
                    sb.append(line).append("\n");
                }
                
                JSONTokener tokener = new JSONTokener(sb.toString());
                JSONObject responseJson = new JSONObject(tokener);
                JSONArray resultsJson = responseJson.getJSONArray("results");
                
                Log.d(Config.SS_TAG, resultsJson.toString());

                JSONObject jsonReturn = resultsJson.getJSONObject(0).getJSONObject("data"); //just the first element since we will have only one return object
                                
                return jsonReturn;
            } else {
            	Log.e(Config.SS_TAG, "Bad status code: " + responseStatusCode);
            }
            
            
		} catch (ClientProtocolException e) {
			Log.e(Config.SS_TAG, "ClientProtocolException in execute()");
			e.printStackTrace();
		} catch (IOException e) {
			Log.e(Config.SS_TAG, "IOException in execute()");
			e.printStackTrace();
		} catch (JSONException e) {
			Log.e(Config.SS_TAG, "JSONException in execute()");
			e.printStackTrace();
		}
		
		Log.e(Config.SS_TAG, "Error while executing: " + jsonRPCMethod.getMethodName());
        return null; //TODO: better error response, for now just return null
	}
	
	public static void resolveSyncData(JSONObject syncResp, myApp app) {
		try {
			//ITERATE OVER EACH LIST
			int numOfLists = syncResp.getInt("numOfLists");
			JSONArray modListNames = syncResp.getJSONArray("listNames");
			JSONArray modListDates = syncResp.getJSONArray("modListDates");
			JSONArray modListItems = syncResp.getJSONArray("listItems");
			for(int i = 0; i < numOfLists; i++) {
				String listName = modListNames.getString(i);
				if (listName.equals("null")) continue;
				int modListDate = modListDates.getInt(i);
				JSONObject itemsObject = modListItems.getJSONObject(i);
				//Log.i(Config.SS_TAG, listName + " " + modListDate + " ");
				
				//Item
				// item name , list name(string) , quantity(string)
				
				//ITERATE OVER EACH LIST'S ITEMS
				ArrayList<Item> newItemList = new ArrayList<Item>();
				int numOfItems = itemsObject.getInt("numOfItems");
				JSONArray modItems = itemsObject.getJSONArray("itemNames");
				JSONArray itemQuantities = itemsObject.getJSONArray("quantities");
				JSONArray itemCheckedVals = itemsObject.getJSONArray("checkedVals");
				for(int j = 0; j < numOfItems; j++ ) {
					String itemName = modItems.getString(j);
					int quantities = itemQuantities.getInt(j);
					int checkedVal = itemCheckedVals.getInt(j);
					Item temp = new Item(itemName, quantities);
					newItemList.add(temp);	
				}
				Log.e(Config.SS_TAG, "pass part 1");
				ShoppingList temp=app.findList(listName);
				if (temp==null) {
					app.addShoppingList(new ShoppingList(listName,new ArrayList(),newItemList));
				}
				else temp.renewShoppingList(newItemList);
				

			}
			
		} catch (JSONException e) {
			Log.e(Config.SS_TAG, "Error building package");
			e.printStackTrace();
		}
		
	}

	public static void testSyncData(JSONObject syncResp) {
		try {
			//ITERATE OVER EACH LIST
			int numOfLists = syncResp.getInt("numOfLists");
			JSONArray modListNames = syncResp.getJSONArray("listNames");
			JSONArray modListDates = syncResp.getJSONArray("modListDates");
			JSONArray modListItems = syncResp.getJSONArray("listItems");
			for(int i = 0; i < numOfLists; i++) {
				String listName = modListNames.getString(i);
				int modListDate = modListDates.getInt(i);
				JSONObject itemsObject = modListItems.getJSONObject(i);
				
				//ITERATE OVER EACH LIST'S ITEMS
				int numOfItems = itemsObject.getInt("numOfItems");
				JSONArray modItems = itemsObject.getJSONArray("itemNames");
				JSONArray itemQuantities = itemsObject.getJSONArray("quantities");
				JSONArray itemCheckedVals = itemsObject.getJSONArray("checkedVals");
				for(int j = 0; j < numOfItems; j++ ) {
					String itemName = modItems.getString(j);
					int quantities = itemQuantities.getInt(j);
					int checkedVal = itemCheckedVals.getInt(j);
					Item temp = new Item(itemName, quantities);
				}

			}
			
		} catch (JSONException e) {
			Log.e(Config.SS_TAG, "Error building package");
			e.printStackTrace();
		}
		
	}
	
	public static void registerDevice(Context context) {
		boolean autoSyncEnabled = !C2DMessaging.getRegistrationId(context).equals("");
		if(!autoSyncEnabled) {
			Log.d(Config.SS_TAG, "Trying to register with C2DM servers...");
			C2DMessaging.register(context, Config.C2DM_EMAIL_ACCOUNT);
		} else {
			Log.d(Config.SS_TAG, "Already registered with C2DM servers...");
		}
	}
	
	public static boolean autoSyncDesired = false;
	public static boolean autoSyncEnabled = false;
}
